package rrd;

import java.util.GregorianCalendar;

/**
 * Class to test all {@link Rrd <b>Rrd</b>} methods. This test consists of several steps:<p>
 * <ol>
 * 		<li> Single RRD database is created.
 * 		<li> Database is updated more than 20.000 times.
 * 		<li> Last update time was tested.
 * 		<li> Sample graph is created.
 * 		<li> Some data is fetched from the RRD database and printed on stdout.
 * </ol><p>
 *
 * If the test passes without exceptions, you are ready to use the full power of RRDTOOL
 * using simple Java interface.<p>
 *
 * This class is part of RRDJTool package freely available from
 * <a href="http://marvin.datagate.co.yu:8081/rrdjtool"
 * target="blank">http://marvin.datagate.co.yu:8081/rrdjtool</a>.<p>
 *
 * @author Sasa Markovic<br><a href="mailto:sasam@dnseurope.co.uk">sasam@dnseurope.co.uk</a><p>
 * @version 1.0.1 (Feb 17, 2003)
 */
public class RrdDemo {

	/**
	 * Used to conduct {@link Rrd <b>Rrd</b>} test.<p>
	 *
	 * Example:<p>
	 * <pre>
	 * java rrd.RrdDemo /tmp/test.rrd
	 * </pre>
	 *
	 * The test is successful if:<p>
	 * <ul>
	 * 		<li>no exception is thrown;
	 * 		<li>test RRD database is found on the file system after the test;
	 * 		<li>sample RRD graph (PNG format) is found in the same directory as the
	 *      test database.
	 * </ul><p>
	 *
	 * The graph should look like this (but not exactly, RRD database is updated with
	 * random values):<p>
	 *
	 * <img src="test.rrd.png" align="center"><p>
	 *
	 * <b>Possible problems</b>
	 *
	 * The only problem you should expect is an <i>UnsatisfiedLinkException</i>. This exception
	 * occurs if JVM cannot find two requested shared libraries:<p>
	 *
	 * <ul>
	 * 		<li><b>librrd.so</b>: Recompile Oetiker's RRDTOOL with --enable-shared flag
	 * 		<li><b>libjrrd.so</b>: Make this library using makefile in the /native directory of
	 *      the source code distribution.
	 * </ul><p>
	 *
	 * If you find both libraries on your file system, check <b>LD_LIBRARY_PATH</b> environment
	 * variable and update it so that both libraries can be found by JVM at runtime.
	 *
	 * @param args Full path to the RRD database which will be created during the test.
	 * All parent directories must exist.
	 * @throws RrdException Thrown if anything fails.
	 */
	public static void main(String[] args) throws RrdException {
		System.err.println("JLP: " + System.getProperty("java.library.path"));
		try {
			String createCmd = "create %DATABASE% --start 999999999 --step 300 " +
				"DS:temp1:GAUGE:1800:U:U " +
				"DS:temp2:GAUGE:1800:U:U " +
				"RRA:AVERAGE:0.5:1:600 RRA:AVERAGE:0.5:6:700 " +
				"RRA:AVERAGE:0.5:24:700 RRA:AVERAGE:0.5:288:700 ";

			String updateCmd = "update %DATABASE% %TIME%:%TEMP1%:%TEMP2%";

			String lastCmd = "last %DATABASE%";

			String graphCmd = "graph %GRAPHNAME% -s %START% -e %END% -a PNG " +
				"-w 450 -h 250 -t \"Moon temperatures\" " +
				"-v \"Measured temperature\" " +
				"DEF:temp1=%DATABASE%:temp1:AVERAGE " +
				"DEF:temp2=%DATABASE%:temp2:AVERAGE " +
				"AREA:temp1#FF0000:shade " +
				"GPRINT:temp1:AVERAGE:\"average %.2lf\\l\" " +
				"LINE1:temp2#0000FF:sunshine " +
				"GPRINT:temp2:AVERAGE:\"average %.2lf\\l\" " +
				"PRINT:temp1:AVERAGE:%.2lf " +
				"PRINT:temp2:AVERAGE:%.2lf ";

			String fetchCmd = "fetch %DATABASE% AVERAGE --start %START% --end %END%";

			if(args.length != 1) {
				System.out.println("Usage: java rrd.Rrd [test RRD database name]");
				return;
			}

			// START TEST
			System.out.println("==== Test started ====");
			Rrd rrd = Rrd.getInstance();

			// CREATE RRD DATABASE
			String cmd1 = createCmd.replaceFirst("%DATABASE%", args[0]);
			System.out.println("Creating RRD database [" + args[0] + "]");
			rrd.create(cmd1);
			System.out.println("RRD database created");

			// UPDATE RRD DATABASE
			GregorianCalendar gcStart = new GregorianCalendar(2003, 0, 1);
			GregorianCalendar gcEnd = new GregorianCalendar(2003, 1, 1);
			long tStart = gcStart.getTime().getTime() / 1000;
			long tEnd = gcEnd.getTime().getTime() / 1000;
			long step = 120; // seconds
			int count = 0;
			System.out.println("Covering one month period (" + tStart + ", " + tEnd +
				"), simulating RRD update each " + step + " seconds");
			double temp1 = 20.0, temp2 = temp1;
			for(long t = tStart; t <= tEnd; t += step) {
				temp1 += Math.random() - 0.5;
				temp1 = Math.max(temp1, 0.0);
				temp2 = temp1 + Math.random() * 40.0 * (t - tStart) / (tEnd - tStart);
				String cmd2 = updateCmd.replaceFirst("%DATABASE%", args[0]);
				cmd2 = cmd2.replaceFirst("%TIME%", "" + t);
				cmd2 = cmd2.replaceFirst("%TEMP1%", "" + temp1);
				cmd2 = cmd2.replaceFirst("%TEMP2%", "" + temp2);
				rrd.update(cmd2);
				if((++count) % 5000 == 0) {
					System.out.println("Database updated " + count + " times");
				}
			}
			System.out.println("One month period covered, " + count + " RRD updates");

			// RRDLAST Test
			String cmd3 = lastCmd.replaceFirst("%DATABASE%", args[0]);
			System.out.println("Last update timestamp was " + rrd.last(cmd3));

			// CREATE GRAPH FOR THE FIRST MONTH AND ONE DAY MORE
			String cmd4 = graphCmd.replaceFirst("%GRAPHNAME%", args[0] + ".png");
			cmd4 = cmd4.replaceFirst("%START%", "" + tStart);
			cmd4 = cmd4.replaceFirst("%END%", "" + (tEnd + 86400));
			cmd4 = cmd4.replaceAll("%DATABASE%", args[0]);
			System.out.println("Creating sample RRD graph [" + args[0] + ".png]");
			String[] lines = rrd.graph(cmd4);
			System.out.println("Graph created with " + lines.length + " extra text lines:");
			for(int i = 0; i < lines.length; i++) {
				System.out.println("Line " + i + ": " + lines[i]);
			}

			// FETCH SOME DATA
			String cmd5 = fetchCmd.replaceFirst("%DATABASE%", args[0]);
			cmd5 = cmd5.replaceFirst("%START%", "" + tStart);
			cmd5 = cmd5.replaceFirst("%END%", "" + tEnd);
			System.out.println("Fetching RRD data");
			Rrd.FetchData data = rrd.fetch(cmd5);
			System.out.println("RRD data fetched, " + data.getRowCount() + " rows returned");
			int rows = data.getRowCount(), cols = data.getColCount();
			for(int i = 0; i < rows; i++) {
				System.out.print(i + ": t=" + data.getTimestamp(i) + " ");
				for(int j = 0; j < cols; j++) {
					System.out.print(data.getColName(j) + "=" + data.getValue(i, j) + " ");
				}
				System.out.println();
			}
			System.out.println("==== Test finished ====");
		} catch (UnsatisfiedLinkError e) {
			System.err.println("JLP: " + System.getProperty("java.library.path"));
			System.err.println(e);
		}
	}
}
